﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using SharpShare.Configuration;
using SharpShare.Diagnostics;
using SharpShare.Management;

namespace SharpShare.Service {
    internal class ConsoleProgram {
        private static object SyncLock = new object();
        private static ShareManager _shareManager;

        public static void ConsoleMain(string[] args) {


            //IStorageContainer container = new FileStorageContainer(new System.IO.DirectoryInfo("X:\\"));
            //IStorageContainer item1 = container.Contents["amazing"].DemandContainer();
            //IStorageContainer child = item1.Contents["child"].DemandContainer();
            //int code = item1.GetHashCode();
            //item1.Rename("amazing");
            //IStorageContainer item2 = container.Contents["amazing"].DemandContainer();
            //int code2 = item2.GetHashCode();

            //item1.Rename("neat");

            //IStorageSearchEngine engine = new TreeStorageSearchEngine(sProvider);

            //var results = engine.Search(
            //    new SearchParameter[] {
            //        new NameSearchParameter("test")
            //    })
            //    .ToList();

            //IStorageFile zipFile = sProvider.Content("New Text Document.zip").DemandFile();

            //ZipArchiveStorageItem zipItem = new ZipArchiveStorageItem(zipFile);

            //var c = zipItem.DemandContainer().Contents().ToList()[0].DemandFile();

            //IStorageDataProvider dataP = c.Open(StorageFileAccess.Read, StorageFileAccess.None);

            //byte[] buffer = new byte[1024];
            //dataP.Read(0, buffer, 0, buffer.Length);


            System.Configuration.Configuration configuration = Program._configuration;

            if (configuration == null) {
                configuration = System.Configuration.ConfigurationManager.OpenExeConfiguration(System.Configuration.ConfigurationUserLevel.None);
            }

            try {
                Console.BackgroundColor = ConsoleColor.White;
                Console.ForegroundColor = ConsoleColor.Black;
                Console.BufferHeight = 120;
                Console.BufferWidth = 190;
                Console.WindowHeight = 60;
                Console.WindowWidth = 180;
            } catch { }

            Console.Clear();

            Log.EntryAdded += new Log.EntryAddedHandler(Log_EntryAdded);

            _shareManager = new ShareManager();

            _shareManager.Start();

            for (; ; ) {
                var key = Console.ReadKey(true);

                if (key.KeyChar == 'x') {
                    break;
                }

                StartAfpTest();
            }

            if (_shareManager.State == ShareManagerState.Started) {
                _shareManager.Stop();
            }

            Thread.Sleep(2000);
        }

        static void StartAfpTest() {
            Log.EntryAdded -= Log_EntryAdded;

            Console.Clear();

            Console.WriteLine("SharpShare Test Console");
            // Console.WriteLine();

            for (; ; ) {
                Console.WriteLine();
                Console.Write("SharpShare> ");
                string command = Console.ReadLine();
                Console.WriteLine();

                string[] splitCommand = command.Split(' ');

                if (splitCommand.Length == 0) {
                    continue;
                }

                string[] args = new string[splitCommand.Length - 1];
                Array.Copy(splitCommand, 1, args, 0, args.Length);

                List<string> finalArgs = new List<string>();

                bool inQuote = false;

                foreach (string a in args) {
                    if (inQuote) {
                        if (a.EndsWith("\"")) {
                            finalArgs[finalArgs.Count - 1] += " " + a.TrimEnd('\"');
                            inQuote = false;
                        } else {
                            finalArgs[finalArgs.Count - 1] += " " + a;
                        }
                    } else {
                        if (a.StartsWith("\"")) {
                            if (a.EndsWith("\"")) {
                                finalArgs.Add(a.TrimStart('\"').TrimEnd('\"'));
                            } else {
                                finalArgs.Add(a.TrimStart('\"'));
                                inQuote = true;
                            }
                        } else {
                            finalArgs.Add(a);
                        }
                    }
                }

                if (!ProcessAfpTestCommand(splitCommand[0], finalArgs.ToArray())) {
                    break;
                }
            }

            Console.Clear();

            Log.EntryAdded += Log_EntryAdded;
        }

        static bool ProcessAfpTestCommand(string command, string[] args) {
            try {
                switch (command) {
                    case "test": {
                            ((IShareManager)_shareManager).Sessions.SelectMany(s => s.OpenFiles).ToList();
                            break;
                        }
                    case "list": {
                            switch (args[0]) {
                                case "sessions": {
                                        Console.WriteLine();
                                        var sessions = _shareManager.Servers.SelectMany(s => s.Sessions).ToList();

                                        Console.WriteLine("{0} Open Session(s)", sessions.Count);
                                        Console.WriteLine();

                                        for (int x = 0; x < sessions.Count; x++) {
                                            Console.WriteLine("+ Session {0}: --------------------", x + 1);
                                            WriteSessionDescription(sessions[x]);
                                            Console.WriteLine();
                                        }

                                        break;
                                    }
                                default: {
                                        Console.WriteLine("Unrecognized list command: {0}", args[0]);
                                        break;
                                    }
                            }
                            break;
                        }
                    case "message": {
                            switch (args[0]) {
                                case "session": {
                                        //var sessions = _shareManager.Servers.SelectMany(s => s.Sessions).ToList();
                                        //IShareSession session = sessions[int.Parse(args[1]) - 1];

                                        //IAfpSession afpSession = (session as IAfpSession);

                                        //if (afpSession == null) {
                                        //    Console.WriteLine("Session {0} is not an AFP session.", session);
                                        //    break;
                                        //}

                                        //Console.WriteLine("Sending message to session '{0}'...", session);

                                        //bool sent = afpSession.SendMessage(args[2], TimeSpan.FromSeconds(5));

                                        //if (!sent) {
                                        //    Console.WriteLine("Timed out waiting for client to grab the message.");
                                        //} else {
                                        //    Console.WriteLine("Message sent.");
                                        //}

                                        break;
                                    }
                                case "broadcast": {

                                        break;
                                    }
                                default: {
                                        Console.WriteLine("Unrecognized message target {0} (expect 'session' or 'broadcast').", args[0]);
                                        break;
                                    }
                            }
                            break;
                        }
                    case "exit":
                        return false;
                    default: {
                            Console.WriteLine("Unknown command: {0}", command);
                            break;
                        }
                }
            } catch (Exception ex) {
                Console.ForegroundColor = ConsoleColor.DarkRed;
                Console.WriteLine("{0}", ex.Message);
                Console.ForegroundColor = ConsoleColor.Black;
            }

            return true;
        }

        static void WriteSessionDescription(IShareSession session) {
            WriteNameValueLine("Type", session.GetType().Name);
            WriteNameValueLine("User", "{0}", session.User == null ? "(not logged in)" : session.User.ToString());

            //IAfpSession afpSession = (session as IAfpSession);

            //if (afpSession != null) {
            //    WriteNameValueLine("Sleeping", (afpSession.IsSleeping ? "Yes" : "No"));
            //    WriteNameValueLine("Endpoint", afpSession.Endpoint == null ? "(no transport)" : afpSession.Endpoint.ToString());
            //    WriteNameValueLine("Authentication Method", afpSession.AuthenticationMethod == null ? "(none yet)" : afpSession.AuthenticationMethod.Name);
            //    WriteNameValueLine("Attention Quantum", "{0}", afpSession.AttentionQuantum);
            //}
        }

        static void WriteNameValueLine(string name, string valueFormat, params object[] args) {
            Console.WriteLine("{0,-25}: {1}", name, string.Format(valueFormat, args));
        }
        private static void Log_EntryAdded(LogEntry entry) {
            if (entry.Type == EntryType.Debug) {
                return;
            }

            entry.WriteToConsole();


        }

    }
}
